﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Manazra.Helpers;

namespace Manazra.Models.Repository
{
    public class ArticleRepository
    {
        //data context
        private ManazraDataContext dc = new ManazraDataContext();

        //get all articles
        public IQueryable<Article> GetAll()
        {
            return dc.Articles;
        }

        //get recent articles
        public IQueryable<Article> GetRecent()
        {
            return dc.Articles.OrderByDescending(a => a.CreatedDate);
        }

        //get popular articles
        public IQueryable<Article> GetPopular()
        {
            return dc.Articles.OrderByDescending(a => a.Points);
        }
                
        //get top few articles
        public IQueryable TopRanked(int count)
        {
            var articles = (from a in dc.Articles
                            orderby a.Points descending
                            where a.Points > 0
                            select new { a.RecId, a.Title, a.Points }).Take(count);
            return articles;
        }

        //get article by id
        public Article GetById(int id)
        {
            return dc.Articles.SingleOrDefault(a => a.RecId == id);
        }

        //get articles listing by category
        public IQueryable<Article> GetByCategory(String category)
        {
            return from a in dc.Articles
                   where a.Category.Title == category
                   orderby a.CreatedDate descending
                   select a;
        }

        //get articles listing by category and popular
        public IQueryable<Article> GetByCategoryAndPopular(string category)
        {
            return from a in dc.Articles
                   where a.Category.Title == category
                   orderby a.Points descending
                   select a;
        }

        //get articles by author
        public IQueryable<Article> GetByAuthor(string author)
        {
            return from a in dc.Articles
                   where a.Author == author
                   orderby a.CreatedDate descending
                   select a;
        }

        //get articles by author ordered by popularity
        public IQueryable<Article> GetByAuthorAndPopular(string author)
        {
            return from a in dc.Articles
                   where a.Author == author
                   orderby a.Points descending
                   select a;
        }

        //get article categories
        public IQueryable<Category> GetCategories()
        {
            return from c in dc.Categories
                   select c;
        }

        //get single category
        public Category GetCategoryById(int id)
        {
            return dc.Categories.SingleOrDefault(c => c.RecId == id);
        }

        //adds a new article
        public void Add(Article article)
        {
            dc.Articles.InsertOnSubmit(article);
        }

        //deletes an article
        public void Delete(Article article)
        {
            //delete any blog connection this article has
            dc.BlogEntries.DeleteAllOnSubmit(from be in dc.BlogEntries
                                             where be.Article == article
                                             select be);
            //first delete all replies
            dc.Replies.DeleteAllOnSubmit(from r in dc.Replies
                                         where r.Comment.ArticleSegment.Article == article
                                         select r);
            //first delete all responses for all segments of this article
            dc.Comments.DeleteAllOnSubmit(from c in dc.Comments
                                          where c.ArticleSegment.Article == article
                                          select c);
            //then delete all segments for this article
            dc.ArticleSegments.DeleteAllOnSubmit(article.ArticleSegments);
            //finally delete the article
            dc.Articles.DeleteOnSubmit(article);
        }

        //saves article segments
        public void SaveSegments(Article article, FormCollection formValues)
        {
            //get article segments information
            int totalSegments = Int32.Parse(formValues["CountParagraphs"]);
            for (int i = 1; i <= totalSegments; i++)
            {
                var remove = formValues["SegmentRemove-" + i];
                //deleteing an existing segment
                if (remove == "true")
                {
                    //get id
                    var segmentId = formValues["SegmentId-" + i];
                    if (!String.IsNullOrEmpty(segmentId))
                    {
                        //get the article segment
                        var segment = article.ArticleSegments.SingleOrDefault(s => s.RecId == Int32.Parse(segmentId));
                        if (segment != null)
                        {
                            //lets gather up how many points will go away with this article segment
                            int points = segment.Comments.Count() * (int)RankPoints.Comment;
                            points += (from r in dc.Replies
                                       where r.Comment.ArticleSegment == segment
                                       select r).Count() * (int)RankPoints.Reply;
                            segment.Article.Points -= points;

                            //first delete all replies for this segment
                            dc.Replies.DeleteAllOnSubmit(from r in dc.Replies
                                                         where r.Comment.ArticleSegment == segment
                                                         select r);
                            //first delete all comments for this segment
                            dc.Comments.DeleteAllOnSubmit(from c in dc.Comments
                                                          where c.ArticleSegment == segment
                                                          select c);
                            //then delete the segment
                            dc.ArticleSegments.DeleteOnSubmit(segment);
                        }
                    }
                }
                //editing an existing segment
                else if (remove == "false")
                {
                    var segmentId = formValues["SegmentId-" + i];
                    if (!String.IsNullOrEmpty(segmentId))
                    {
                        //get the article segment
                        var segment = article.ArticleSegments.SingleOrDefault(s => s.RecId == Int32.Parse(segmentId));
                        if (segment != null)
                        {
                            //update its properties
                            segment.Content = HttpUtility.HtmlEncode(formValues["Segment-" + i]);
                        }
                    }
                }
                //new segment
                else
                {
                    var content = formValues["Segment-" + i];
                    if (!String.IsNullOrEmpty(content))
                    {
                        var segment = new ArticleSegment();
                        segment.Discussable = true;
                        segment.Content = HttpUtility.HtmlEncode(content);
                        //add to article
                        article.ArticleSegments.Add(segment);
                    }
                }
            }
        }

        //add points to article - for viewing
        public void AddPoints(Article article)
        {
            article.Points += (int)RankPoints.View;
        }

        //save
        public void Save()
        {
            dc.Log = new DebuggerWriter();
            dc.SubmitChanges();
        }
    }
}
